#include "vcl_stl.h"

#include "bkbase.h"
#include "h_base.h"
#include "h_xml.h"
using namespace h_base;

#include "simbat.h"
using namespace simbat;

static char *SimbatBase;
static char ErrMsg[8192 + 1];

static HString SyslogDir;
static HSyslog Syslog;
static HString ShrDir;
static HString JobNameDelimiter = ":";

static void LoadFromCfg(HXmlTree &Cfg)
{
   SyslogDir = EnvEvaluate(Cfg.GetValue("SYSLOG_DIR", "$SIMBAT_BASE/etc"));
   Syslog.Setup(SyslogDir, Cfg.GetValueUpper("SYSLOG_LEVEL", "INFO"));
   ShrDir = EnvEvaluate(Cfg.GetValue("SHR_DIR", "$SIMBAT_BASE/shr"));
   JobNameDelimiter = Cfg.GetValue("JOB_NAME_DELIMITER", ":");
}

static bool LoadCfg(HString &ErrStr)
{
   char FileName[500 + 1];
   HXmlTree Cfg;

   {
      HFileLockRead Lock("$SIMBAT_BASE/tmp/config.lck");
      snprintf(FileName, 500, "%s/etc/config.xml", SimbatBase);
      if ( !Cfg.LoadFromFile(FileName) )
      {
         ErrStr = Cfg.GetErrorString();
         return false;
      }
   }

   LoadFromCfg(Cfg);
   return true;
}

static string FormatTime(const char *s)
{
   char Str[8 + 6 + 1];

   memset(Str, '0', 8 + 6);
   Str[8 + 6] = '\0';

   for ( int i = 0; i < 8 + 6 && *s != '\0'; s++ )
   {
      if ( isdigit(*s) )
      {
         Str[i++] = *s;
      }
   }

   return string(Str);
}

void PrintUsage()
{
   fprintf(stderr, "Usage : [PATH]/simbat_query [--start_rec=?] [--end_rec=?] [--start_time=?] [--end_time=?] job_name|all\n");
}

int main(int argc, char *argv[])
{
   if ( strchr(argv[0], '/') != NULL )
   {
      SetBaseByPath(argv[0]);
   }

   string StartTime;
   string EndTime;
   int StartRec = 0;
   int EndRec = 0;
   string JobName;
   int JobPartIdx = -1;

   int i;

   for ( i = 1; i < argc; i++ )
   {
      if ( memcmp(argv[i], "--start_rec", 11) == 0 )
      {
         StartRec = StrToInt(argv[i] + 11);
         continue;
      }
      if ( memcmp(argv[i], "--end_rec", 9) == 0 )
      {
         EndRec = StrToInt(argv[i] + 9);
         continue;
      }
      if ( memcmp(argv[i], "--start_time", 12) == 0 )
      {
         StartTime = FormatTime(argv[i] + 12);
         continue;
      }
      if ( memcmp(argv[i], "--end_time", 10) == 0 )
      {
         EndTime = FormatTime(argv[i] + 10);
         continue;
      }
      break;
   }

   if ( i + 1 != argc )
   {
      PrintUsage();
      return 8;
   }

   SimbatBase = getenv("SIMBAT_BASE");

   if ( SimbatBase == NULL )
   {
      fprintf(stderr, "$SIMBAT_BASE not defined\n");
      return 8;
   }

   HString ErrStr;

   if ( !LoadCfg(ErrStr) )
   {
      BkPrintError("Load config.xml fail, %s", ErrStr.c_str());
      return 8;
   }

   if ( strcmp(argv[i], "all") == 0 )
   {
      JobName = argv[i];
   }
   else
   {
      vector<string> StrVec;
      SplitString(argv[i], JobNameDelimiter[0], StrVec, true);
      if ( StrVec.size() != 2 && StrVec.size() != 3 )
      {
         PrintUsage();
         return 8;
      }
      JobName = StrVec[0] + JobNameDelimiter + StrVec[1];
      if ( StrVec.size() == 3 )
      {
         JobPartIdx = StrToInt(StrVec[2].c_str()) - 1;
      }
   }

   HString FileName = ShrDir + "/status/job_events";
   FILE *f = fopen(FileName.c_str(), "rb");

   if ( f == NULL )
   {
      BkPrintError("Can not open %s, errno = $d", FileName.c_str(), errno);
      return 8;
   }

   for ( int RecNo = 0; ; )
   {
      HJobEvent Event;
      if ( fread(&Event, sizeof(HJobEvent), 1, f) != 1 )
      {
         break;
      }
      RecNo++;
      if ( strcmp(Event.EyeCatcher, "EMPTY") == 0 )
      {
         break;
      }
      if ( StartRec != 0 && RecNo < StartRec )
      {
         continue;
      }
      if ( EndRec != 0 && RecNo > EndRec )
      {
         break;
      }
      if ( StartTime != "" && strcmp(Event.Time, StartTime.c_str()) < 0 )
      {
         continue;
      }
      if ( EndTime != "" && strcmp(Event.Time, EndTime.c_str()) > 0 )
      {
         break;
      }
      if ( JobName != "all" && strcmp(Event.JobName, JobName.c_str()) != 0 )
      {
         continue;
      }
      if ( JobPartIdx != -1 && JobPartIdx != Event.PartIdx )
      {
         continue;
      }
      printf("%8d, %s", RecNo, Event.JobName);
      if ( Event.PartIdx >= 0 )
      {
         printf("%s%05d", JobNameDelimiter.c_str(), Event.PartIdx + 1);
      }
      printf(", %.4s/%.2s/%.2s.%.2s:%.2s:%.2s, %d, %d, %d, %s\n",
         Event.Time, Event.Time + 4, Event.Time + 4 + 2,
         Event.Time + 4 + 2 + 2, Event.Time + 4 + 2 + 2 + 2, Event.Time + 4 + 2 + 2 + 2 + 2,
         Event.NumOfPart, Event.ServerId, Event.Pid, JobStatusToString(Event.Status));
   }

   fclose(f);
   return 0;
}
